﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Data.SqlClient;
//using System.Data.SQLite;
using System.Data.SQLite;
using Com.FirstSolver.Splash;


namespace DATA_SERVER
{
    class HANVON_Service : Service, IDgramPacketHandler
    {
        private class HANVON_Deivce
        {
            public string strSN = string.Empty;             //门禁机序列号
            public IPAddress DeviceAddress = null;          //门禁机地址
            public string BeaconName = string.Empty;        //门禁机名称
            public string Position = string.Empty;          //门禁机排序号
            public int InOut = 0;                           //出入类型
            public int Delay = 0;                           //网络延时
            public bool Connected = false;                  //连接状态
        }

        [Serializable]
        private class HANVON_UserInfo
        {
            public string authority = "0X11";               //权限
            public string check_type = "card";              //考勤类型
            public string opendoor_type = "card";           //开门方式
            public string calid = String.Empty;             
            public string alg_edition = String.Empty;
            public string finger_data = String.Empty;           //指纹
            public List<string> face_data = new List<string>(); //人脸
            
        }

        private const int DeviceCodePage = 936;

        private static List<HANVON_Deivce> DeviceList = new List<HANVON_Deivce>();  //设备列表

        private TcpListenerPlus TcpServer = null;
        private UdpClientPlus UdpServer = null;

        //服务启动
        public override void StartService()
        {
            isStop = false;

            Thread listenThread = new Thread(new ThreadStart(StartListen));
            listenThread.IsBackground = true;
            listenThread.Start();
        }

        //停止服务
        public override void StopService()
        {
            if (isStop)
            {
                return;
            }

            isStop = true;

            TcpServer.Stop();
            TcpServer = null;

            UdpServer.Close();
            UdpServer = null;

            DeviceList.Clear();

            Data_Func.ShowText("已停止监听！");
        }

        //向门禁机发送新用户
        public override void AddUser(string pin, string name, string cardno, string type, string extra)
        {
            HANVON_UserInfo userinfo;
            if ((type == "HW") && (extra.Length > 0))
            {
                userinfo = Data_Func.Deserialize(extra) as HANVON_UserInfo;
            }
            else
            {
                userinfo = new HANVON_UserInfo();
            }

            string command = "SetEmployee(id=\"" + pin + "\" name=\"" + name + "\"";
            if (cardno.Length > 0)
            {
                long i_cardno = 0;
                long.TryParse(cardno, out i_cardno);
                string str_card = Convert.ToString(i_cardno, 16);
                string str_new_card = shift_fun3(str_card);
                //进行高低位转换
                //for (int i = 0; i < str_card.Length; i = i + 2)
                //{
                //    str_new_card += str_card[i + 1].ToString() + str_card[i].ToString() + " ";
                //}
                //if (str_card.Length > 8)
                //    str_card = str_card.Substring(0, 8);
                //command += " card_num=\"0X" + str_card + "\"";

                 command += " card_num=\"0X" + str_new_card + "\"";
            }
            command += " authority=\"" + userinfo.authority + "\" check_type=\"" + userinfo.check_type + "\" opendoor_type=\"" + userinfo.opendoor_type + "\"";
            if (userinfo.calid.Length > 0)
            {
                command += " calid=\"" + userinfo.calid + "\"";
            }
            if (userinfo.alg_edition.Length > 0)
            {
                command += " alg_editio=\"" + userinfo.alg_edition + "\"";
            }
            if (userinfo.finger_data.Length > 0)
            {
                command += "\nfinger_data=\"" + userinfo.finger_data + "\"";
            }
            foreach(string face_data in userinfo.face_data)
            {
                if (face_data.Length > 0)
                {
                    command += "\nface_data=\"" + face_data + "\"";
                }
            }
            command += ")";

            Execute(command);
        }

        public string shift_fun3(string data)
        {
            int n = data.Length;
            //if (n < 8) return data;
            if (n < 8)
            {
                // 补成8位
                data = data.ToString().PadLeft(8, '0');
            }

            string str_card = data.Substring(6, 2) + data.Substring(4, 2) + data.Substring(2, 2) + data.Substring(0, 2);
            return str_card;
        }

        //删除门禁机指定用户
        public override void DelUser(string pin)
        {
            string command = "DeleteEmployee(id=\"" + pin + "\")";

            Execute(command);
        }

        //清空门禁机中所有用户
        public override void ClearUser()
        {
            Execute("DeleteAllEmployee()");
        }

        //检测门禁机状态
        public override string CheckConnect()
        {
            string tmpstr = DeviceList.Count.ToString() + "\t";

            for (int i = 0; i < DeviceList.Count; i++)
            {
                DeviceList[i].Delay += Global.NetInterval;
                if ((DeviceList[i].Connected) && (DeviceList[i].Delay > 120))
                {
                    DeviceList[i].Connected = false;
                    Data_Func.ShowText("门禁设备 <" + DeviceList[i].BeaconName + "> 已断开");
                }
                tmpstr += DeviceList[i].BeaconName + "\t" + DeviceList[i].InOut + "\t" + (DeviceList[i].Connected ? "1" : "0") + "\t";
            }

            return tmpstr;
        }

        //启动监听线程函数
        private void StartListen()
        {
            while (!isStop)
            { 

                try
                {
                    TcpServer = new TcpListenerPlus(IPAddress.Any, Global.ServerPort);
                    TcpServer.OnServerTaskRequest += OnServerTaskProcess;
                    TcpServer.StartListenThread(null, 0, 600000);

                    UdpServer = new UdpClientPlus(Global.ServerPort + 1);
                    UdpServer.CodePage = DeviceCodePage;
                    UdpServer.DgramPacketHandler = this;
                    UdpServer.StartListenThread();

                    Data_Func.ShowText("开始监听 " + Global.ServerPort + " 端口");
                    break;
                }
                catch
                {
                    TcpServer = null;
                    Data_Func.ShowText("网络连接失败！");
                    Thread.Sleep(10000);
                    continue;
                }
            }
        }

        //数据处理函数
        private void OnServerTaskProcess(object sender, EventArgs e)
        {
            NetworkStreamPlus Stream = (NetworkStreamPlus)sender;

            string strSN = string.Empty;
            HANVON_Deivce pDevice = null;
            while (true)
            {
                try
                {
                    string Answer;
                    Stream.Read(out Answer, DeviceCodePage);

                    if (Answer.StartsWith("PostRecord"))            //门禁记录开始标志
                    {
                        strSN = FaceId_Item.GetKeyValue(Answer, "sn");
                        pDevice = GetDevice(strSN);
                        if (pDevice == null)
                        {
                            pDevice = NewDevice(strSN);
                        }

                        Stream.Write("Return(result=\"success\" postphoto=\"false\")", DeviceCodePage);
                    }
                    else if (Answer.StartsWith("Record"))           //门禁记录条目
                    {
                        ProcessRecord(Answer, pDevice);

                        Stream.Write("Return(result=\"success\")", DeviceCodePage);
                    }
                    else if (Answer.StartsWith("PostEmployee"))     //人员信息开始标志
                    {
                        strSN = FaceId_Item.GetKeyValue(Answer, "sn");
                        pDevice = GetDevice(strSN);
                        if (pDevice == null)
                        {
                            pDevice = NewDevice(strSN);
                        }

                        Stream.Write("Return(result=\"success\")", DeviceCodePage);
                    }
                    else if (Answer.StartsWith("Employee"))         //人员信息条目
                    {
                        ProcessEmployee(Answer);

                        Stream.Write("Return(result=\"success\")", DeviceCodePage);
                    }
                    else if (Answer.StartsWith("GetRequest"))       //定时请求指令
                    {
                        //同步时间命令
                        string Command = "SetDateTime(date=\"" + DateTime.Now.ToString("yyyy-MM-dd") + "\" time=\"" + DateTime.Now.ToString("HH:mm:ss") + "\")";
                        Stream.Write(Command, DeviceCodePage);
                    }
                    else if (Answer.StartsWith("Quit"))             //结束标志
                    {
                        break;
                    }
                    else
                    {
                        break;
                    }
                }
                catch
                {
                    break;
                }
            }
        }

        //心跳信号处理函数
        public void OnDgramPacketReceived(IPEndPoint remoteEP, string content)
        {
            if (!content.StartsWith("DevStatus"))
            {
                return;
            }
            string strSN = FaceId_Item.GetKeyValue(content, "sn");
            HANVON_Deivce pDevice = GetDevice(strSN);
            if (pDevice == null)
            {
                pDevice = NewDevice(strSN);
            }

            pDevice.Delay = 0;
            if (pDevice.Connected == false)
            {
                pDevice.Connected = true;
                Data_Func.ShowText("门禁设备 <" + pDevice.BeaconName + "> 已连接"); 
            }
            if (pDevice.DeviceAddress != remoteEP.Address)
            {
                pDevice.DeviceAddress = remoteEP.Address;
            }
        }

        public void OnDgramPacketReceived(IPEndPoint remoteEP, byte[] content)
        {
        }

        //新设备处理函数
        private HANVON_Deivce NewDevice(string strSN)
        {
            HANVON_Deivce pDevice = new HANVON_Deivce();
            pDevice.strSN = strSN;
            pDevice.BeaconName = "未知设备" + strSN;

            try
            {
                SQLiteDataReader reader = DB_SQLite.ExecuteReader(string.Format("SELECT [BeaconName],[BeaType],[Line] FROM [T_JC_Beacon] WHERE [BeaMac] = '{0}'", strSN));

                if (reader.Read())
                {
                    pDevice.BeaconName = reader[0].ToString();
                    if (reader[1].ToString() == "JZWZLY004")
                    {
                        pDevice.InOut = 1;
                    }
                    else if (reader[1].ToString() == "JZWZLY005")
                    {
                        pDevice.InOut = 2;
                    }
                    pDevice.Position = reader[2].ToString();
                }
                reader.Close();
            }
            catch { }

            if ((pDevice.InOut == 0) && (DB_SQLServer.b_Init))
            {
                try
                {
                    SqlDataReader reader = DB_SQLServer.ExecuteReader(string.Format("SELECT [BeaconName],[BeaType],[Line] FROM [T_JC_Beacon] WHERE [BeaMac] = '{0}'", strSN));

                    if (reader.Read())
                    {
                        pDevice.BeaconName = reader[0].ToString();
                        if (reader[1].ToString() == "JZWZLY004")
                        {
                            pDevice.InOut = 1;
                        }
                        else if (reader[1].ToString() == "JZWZLY005")
                        {
                            pDevice.InOut = 2;
                        }
                        pDevice.Position = reader[2].ToString();
                    }
                    reader.Close();
                }
                catch { }
            }

            int pos = 0;
            for (int i = 0; i < DeviceList.Count; i++)
            {
                if (string.Compare(DeviceList[i].Position, pDevice.Position) <= 0)
                {
                    pos++;
                }
                else
                {
                    break;
                }
            }
            DeviceList.Insert(pos, pDevice);

            return pDevice;
        }

        //门禁记录处理函数
        private void ProcessRecord(string Answer, HANVON_Deivce pDevice)
        {
            FaceId_Item[] Record_Arr = FaceId_Item.GetAllItems(Answer);
            string time = string.Empty, pin = string.Empty;
            for (int i = 0; i < Record_Arr.Length; i++)
            {
                if (Record_Arr[i].Name == "id")
                {
                    pin = Record_Arr[i].Value;
                }
                else if (Record_Arr[i].Name == "time")
                {
                    time = Record_Arr[i].Value;
                }
            }  
            GetRecord(pin, time, DeviceList.IndexOf(pDevice), pDevice.strSN, pDevice.BeaconName);
        }

        //人员信息处理函数
        private void ProcessEmployee(string Answer)
        {
            FaceId_Item[] Employee_Arr = FaceId_Item.GetAllItems(Answer);
            string pin = string.Empty;
            for (int i = 0; i < Employee_Arr.Length; i++)
            {
                if (Employee_Arr[i].Name == "id")
                {
                    pin = Employee_Arr[i].Value;        //编号
                    break;
                }
            }

            if (pin.Length <= 0)
            {
                return;
            }

            string extra = GetUser(pin, "HW");
            HANVON_UserInfo userinfo;
            if (extra.Length > 0)
            {
                userinfo = Data_Func.Deserialize(extra) as HANVON_UserInfo; //反序列化
            }
            else
            {
                userinfo = new HANVON_UserInfo();
            }

            for (int i = 0; i < Employee_Arr.Length; i++)
            {
                if (Employee_Arr[i].Name == "authority")
                {
                    userinfo.authority = Employee_Arr[i].Value;
                }
                else if (Employee_Arr[i].Name == "check_type")
                {
                    userinfo.check_type = Employee_Arr[i].Value;
                }
                else if (Employee_Arr[i].Name == "opendoor_type")
                {
                    userinfo.opendoor_type = Employee_Arr[i].Value;
                }
                else if (Employee_Arr[i].Name == "calid")
                {
                    userinfo.calid = Employee_Arr[i].Value;
                }
                else if (Employee_Arr[i].Name == "alg_edition")
                {
                    userinfo.alg_edition = Employee_Arr[i].Value;
                }
                else if (Employee_Arr[i].Name == "finger_data")
                {
                    userinfo.finger_data = Employee_Arr[i].Value;
                }
                else if (Employee_Arr[i].Name == "face_data")
                {
                    userinfo.face_data.Add(Employee_Arr[i].Value);
                }
            }

            extra = Data_Func.Serialize(userinfo);
            //Data_Func.ShowText("拼装数据："+ extra);
            SaveUser(pin, "HW", extra);
        }

        //根据序列号从门禁机列表中读取对应门禁机
        private HANVON_Deivce GetDevice(string strSN)
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                if (strSN == DeviceList[i].strSN)
                {
                    return DeviceList[i];
                }
            }
            return null;
        }

        //向门禁机发送命令并执行
        private void Execute(string command)
        {
            for (int i = 0; i < DeviceList.Count; i++)
            {
                try
                {
                    using (FaceId Client = new FaceId(DeviceList[i].DeviceAddress))
                    {
                        string Answer;
                        FaceId_ErrorCode ErrorCode = Client.Execute(command, out Answer, DeviceCodePage);
                        if (ErrorCode == FaceId_ErrorCode.Success)
                        {
                            Data_Func.ShowText("<" + DeviceList[i].BeaconName + "> 命令执行成功");
                            //Data_Func.ShowText("<" + command + ">");
                        }
                        else
                        {
                            Data_Func.ShowText("<" + DeviceList[i].BeaconName + "> 命令执行失败");
                            Data_Func.ShowText("<" + command + ">");   //失败人员信息
                        }
                    }
                }
                catch
                {
                    Data_Func.ShowText("向 <" + DeviceList[i].BeaconName + "> 发送命令出现错误");
                }
            }
        }
    }
}
